from typing import Dict, Any, List
import csv
import os
from .base_formatter import BaseFormatter

class CSVFormatter(BaseFormatter):
    """CSV报告格式化器"""
    
    def format_report(self, results: List[Dict[str, Any]], scan_info: Dict[str, Any]) -> None:
        """生成CSV格式的报告
        
        Args:
            results: 扫描结果列表
            scan_info: 扫描信息字典
        """
        filename = os.path.join(self.output_dir, 'scan_report.csv')
        
        with open(filename, 'w', newline='', encoding='utf-8-sig') as f:
            writer = csv.writer(f)
            
            # 写入扫描信息
            writer.writerow(['扫描信息'])
            writer.writerow(['开始时间', self._format_timestamp(scan_info['start_time'])])
            writer.writerow(['结束时间', self._format_timestamp(scan_info['end_time'])])
            writer.writerow(['扫描主机数', scan_info['total_hosts']])
            writer.writerow(['扫描端口数', scan_info['total_ports']])
            writer.writerow(['开放端口数', len([r for r in results if r['status'] == 'open'])])
            writer.writerow([])  # 空行分隔
            
            # 定义表头
            headers = [
                '目标IP',
                '端口号',
                '状态',
                '服务',
                '响应时间',
                '产品名称',
                '产品版本',
                'Banner信息',
                # 通用信息
                '操作系统',
                '认证方式',
                # FTP特定信息
                'FTP匿名访问',
                'FTP支持特性',
                # SSH特定信息
                'SSH协议版本',
                '密钥类型',
                '密钥长度',
                '密钥指纹',
                'SSH加密算法',
                # HTTP/HTTPS特定信息
                'HTTP状态码',
                '网页标题',
                'Web服务器',
                'HTTP头信息',
                'SSL/TLS版本',
                'SSL/TLS加密套件',
                '证书主体',
                '证书颁发者',
                '证书过期时间',
                # 数据库特定信息
                '数据库类型',
                '数据库版本',
                '数据库认证方式',
                '数据库SSL要求',
                # 邮件服务特定信息
                '邮件服务版本',
                'STARTTLS支持',
                'SSL/TLS支持',
                # 远程桌面特定信息
                '安全级别',
                '加密级别',
                '远程桌面系统信息'
            ]
            writer.writerow(headers)
            
            # 写入扫描结果
            status_map = {
                'open': '开放',
                'closed': '关闭',
                'filtered': '被过滤'
            }
            
            for result in sorted(results, key=lambda x: (x['target'], x['port'])):
                status = status_map.get(result['status'], result['status'])
                service = result['service'] if result['service'] else "未知"
                latency = f"{result['latency']}ms" if result['latency'] else "N/A"
                
                # 获取服务信息
                info = result['service_info'] if result['service_info'] else {}
                
                # 基本信息
                row_data = [
                    result['target'],
                    result['port'],
                    status,
                    service,
                    latency,
                    info.get('product', ''),
                    info.get('version', ''),
                    info.get('banner', ''),
                    info.get('os_type', ''),
                    ', '.join(info.get('auth_methods', [])),
                ]
                
                # FTP特定信息
                if info.get('name') == 'ftp':
                    row_data.extend([
                        '允许' if info.get('anonymous') else '禁止',
                        ', '.join(info.get('features', [])),
                    ])
                else:
                    row_data.extend(['', ''])
                
                # SSH特定信息
                if info.get('name') == 'ssh':
                    row_data.extend([
                        info.get('protocol_version', ''),
                        info.get('key_type', ''),
                        f"{info.get('key_bits', '')}位" if info.get('key_bits') else '',
                        info.get('fingerprint', ''),
                        ', '.join(info.get('encryption_algorithms', [])),
                    ])
                else:
                    row_data.extend(['', '', '', '', ''])
                
                # HTTP/HTTPS特定信息
                if info.get('name') in ['http', 'https']:
                    ssl_info = info.get('ssl_info', {})
                    http_headers = info.get('http_headers', {})
                    row_data.extend([
                        info.get('http_code', ''),
                        info.get('http_title', ''),
                        info.get('http_server', ''),
                        '; '.join([f"{k}: {v}" for k, v in http_headers.items()]),
                        ssl_info.get('version', ''),
                        ssl_info.get('cipher', ''),
                        ssl_info.get('cert_subject', ''),
                        ssl_info.get('cert_issuer', ''),
                        ssl_info.get('cert_expire', ''),
                    ])
                else:
                    row_data.extend(['', '', '', '', '', '', '', '', ''])
                
                # 数据库特定信息
                if info.get('name') in ['mysql', 'postgresql', 'mssql', 'oracle', 'mongodb']:
                    row_data.extend([
                        info.get('db_type', ''),
                        info.get('db_version', ''),
                        info.get('auth_method', ''),
                        '是' if info.get('requires_ssl') else '否',
                    ])
                else:
                    row_data.extend(['', '', '', ''])
                
                # 邮件服务特定信息
                if info.get('name') in ['smtp', 'pop3', 'imap']:
                    row_data.extend([
                        info.get('mail_version', ''),
                        '是' if info.get('starttls_supported') else '否',
                        '是' if info.get('ssl_tls_supported') else '否',
                    ])
                else:
                    row_data.extend(['', '', ''])
                
                # 远程桌面特定信息
                if info.get('name') in ['rdp', 'vnc']:
                    row_data.extend([
                        info.get('security_level', ''),
                        info.get('encryption_level', ''),
                        info.get('os_info', ''),
                    ])
                else:
                    row_data.extend(['', '', ''])
                
                writer.writerow(row_data) 